﻿// ==================================================================================================
// Copyright(C) 2012 NCS Pte. Ltd. All rights reserved.
//
// SYSTEM NAME	    : iConnect .Net Application Framework
// COMPONENT ID	    : NCS.IConnect.Core
// COMPONENT DESC   : The foundation component of the whole framework. 	
//
// CREATED DATE/BY  : 13 Apr 2012 / Wu Yong Qing
//
// REVISION HISTORY :	
// DATE/BY			SR#/CS/PM#/OTHERS		DESCRIPTION OF CHANGE
// ==================================================================================================


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using Microsoft.Practices.Unity.InterceptionExtension;
using NCS.IConnect.Core.Properties;
using NCS.IConnect.Core.Utilities;

namespace NCS.IConnect.Core.IoC.TransientCall
{
    /// <summary>
    /// Transient call intercept.
    /// </summary>
    public static class TransientCallIntercept
    {
        /// <summary>
        /// Gets the proxy.
        /// </summary>
        /// <param name="interceptedType">Type of the intercepted.</param>
        /// <param name="instanceProvider">The instance provider.</param>
        /// <param name="interceptor">The interceptor.</param>
        /// <param name="interceptionBehaviors">The interception behaviors.</param>
        /// <returns>
        /// Transient call proxy instance.
        /// </returns>
        public static object GetProxy(Type interceptedType, IInstanceProvider instanceProvider, ITransientCallInterceptor interceptor, IEnumerable<IInterceptionBehavior> interceptionBehaviors)
        {
            Guard.ArgumentNotNull(interceptedType, "interceptedType");
            Guard.ArgumentNotNull(instanceProvider, "instanceProvider");
            Guard.ArgumentNotNull(interceptor, "interceptor");
            Guard.ArgumentNotNull(interceptionBehaviors, "interceptionBehaviors");

            if (!interceptedType.IsInterface || interceptedType.IsGenericType || interceptedType.IsGenericTypeDefinition)
            {
                throw new ArgumentException(ResourceUtility.Format(Resources.ExceptionTransientCallInterceptOnlyForNonGenericInterface));
            }

            if (!interceptor.CanIntercept(interceptedType))
            {
                throw new ArgumentException(ResourceUtility.Format("InterceptionNotSupportedForTransientCall", interceptedType.FullName));
            }

            var transientCallProxy = interceptor.CreateProxy(interceptedType, instanceProvider);

            return Intercept.ThroughProxy(interceptedType, transientCallProxy, new InterfaceInterceptor(), interceptionBehaviors);
        }

        /// <summary>
        /// Gets the proxy.
        /// </summary>
        /// <param name="interceptedType">Type of the intercepted.</param>
        /// <param name="instanceProvider">The instance provider.</param>
        /// <param name="interceptionBehaviors">The interception behaviors.</param>
        /// <returns>
        /// Transient call proxy instance.
        /// </returns>
        public static object GetProxy(Type interceptedType, IInstanceProvider instanceProvider, IEnumerable<IInterceptionBehavior> interceptionBehaviors)
        {
            return GetProxy(interceptedType, instanceProvider, new DefaultTransientCallInterceptor(), interceptionBehaviors);
        }

        /// <summary>
        /// Gets the proxy.
        /// </summary>
        /// <typeparam name="T">Type of the intercepted.</typeparam>
        /// <param name="instanceProvider">The instance provider.</param>
        /// <param name="interceptor">The interceptor.</param>
        /// <param name="interceptionBehaviors">The interception behaviors.</param>
        /// <returns>
        /// Transient call proxy instance.
        /// </returns>
        public static T GetProxy<T>(IInstanceProvider instanceProvider, ITransientCallInterceptor interceptor, IEnumerable<IInterceptionBehavior> interceptionBehaviors) 
            where T : class
        {
            return (T)GetProxy(typeof(T), instanceProvider, interceptor, interceptionBehaviors);
        }

        /// <summary>
        /// Gets the proxy.
        /// </summary>
        /// <typeparam name="T">Type of the intercepted.</typeparam>
        /// <param name="instanceProvider">The instance provider.</param>
        /// <param name="interceptionBehaviors">The interception behaviors.</param>
        /// <returns>
        /// Transient call proxy instance.
        /// </returns>
        public static T GetProxy<T>(IInstanceProvider instanceProvider, IEnumerable<IInterceptionBehavior> interceptionBehaviors)
            where T : class
        {
            return (T)GetProxy(typeof(T), instanceProvider, new DefaultTransientCallInterceptor(), interceptionBehaviors);
        }
    }
}
